/*
 * @ : Copyright (c) 2021 Phytium Information Technology, Inc. 
 *  
 * SPDX-License-Identifier: Apache-2.0.
 * 
 * @Date: 2021-07-20 08:13:49
 * @LastEditTime: 2021-08-04 08:38:05
 * @Description:  This files is for 
 * 
 * @Modify History: 
 *  Ver   Who        Date         Changes
 * ----- ------     --------    --------------------------------------
 */

#ifndef BSP_DRIVERS_NOR_QSPI_H
#define BSP_DRIVERS_NOR_QSPI_H

#ifdef __cplusplus
extern "C"
{
#endif

#include "kernel.h"
#include "ft_types.h"
#include "ft_error_code.h"
#include "ft_debug.h"

#define QSPI_SUCCESS     FT_SUCCESS  
#define QSPI_INVALID_PARM FT_MAKE_ERRCODE(ErrModBsp, ErrBspQSpi, BIT(1))
#define QSPI_NOT_READY    FT_MAKE_ERRCODE(ErrModBsp, ErrBspQSpi, BIT(2))
#define QSPI_INVALID_PARA FT_MAKE_ERRCODE(ErrModBsp, ErrBspQSpi, BIT(3))
#define QSPI_NOT_ALLIGN   FT_MAKE_ERRCODE(ErrModBsp, ErrBspQSpi, BIT(4))
#define QSPI_NOT_SUPPORT  FT_MAKE_ERRCODE(ErrModBsp, ErrBspQSpi, BIT(5))
#define QSPI_TIMEOUT      FT_MAKE_ERRCODE(ErrModBsp, ErrBspQSpi, BIT(6))

#define QSPI_DEBUG_TAG "QSPI"
#define QSPI_ERROR(format, ...)   FT_DEBUG_PRINT_E(QSPI_DEBUG_TAG, format, ##__VA_ARGS__)
#define QSPI_INFO(format, ...) FT_DEBUG_PRINT_I(QSPI_DEBUG_TAG, format, ##__VA_ARGS__)
#define QSPI_DEBUG(format, ...) FT_DEBUG_PRINT_D(QSPI_DEBUG_TAG, format, ##__VA_ARGS__)

/* QSPI Trasnfer mode */
typedef enum
{
    QSPI_TRANSFER_1_1_1 = 0x0,
    QSPI_TRANSFER_1_1_2 = 0x1,
    QSPI_TRANSFER_1_1_4 = 0x2,
    QSPI_TRANSFER_1_2_2 = 0x3,
    QSPI_TRANSFER_1_4_4 = 0x4,
    QSPI_TRANSFER_2_2_2 = 0x5,
    QSPI_TRANSFER_4_4_4 = 0x6
}QSpiTransferMode;

/* QSPI Flash Capcity type */
typedef enum
{
    QSPI_FLASH_CAP_4MB = 0b000,
    QSPI_FLASH_CAP_8MB = 0b001,
    QSPI_FLASH_CAP_16MB = 0b010,
    QSPI_FLASH_CAP_32MB = 0b011,
    QSPI_FLASH_CAP_64MB = 0b100,
    QSPI_FLASH_CAP_128MB = 0b101,
    QSPI_FLASH_CAP_256MB = 0b110,
}QSpiFlashCapcityType;

typedef enum
{
    QSPI_SCK_DIV_128 = 0x0,
    QSPI_SCK_DIV_2 = 0x1,
    QSPI_SCK_DIV_4 = 0x2,
    QSPI_SCK_DIV_8 = 0x3,
    QSPI_SCK_DIV_16 = 0x4,
    QSPI_SCK_DIV_32 = 0x5,
    QSPI_SCK_DIV_64 = 0x6
}QSpiSckDivType;

/* QSPI Address type */
typedef enum
{
    QSPI_ADDR_SEL_3 = 0x0,
    QSPI_ADDR_SEL_4 = 0x1,
}QSpiAddrType;

typedef enum
{
    QSPI_CHIP_SEL_0 = 0x0,
    QSPI_CHIP_SEL_1 = 0x1,
    QSPI_CHIP_SEL_2 = 0x2,
    QSPI_CHIP_SEL_3 = 0x3,
}QSpiChipSel;

typedef enum
{
    QSPI_ADDR_OPTION
}QSpiOptions;

#define QSPI_FLASH_CMD_WRR 0x01        /* Write status register */
#define QSPI_FLASH_CMD_PP 0x02         /* Page program */
#define QSPI_FLASH_CMD_READ 0x03       /* Normal read data bytes */
#define QSPI_FLASH_CMD_WRDI 0x04       /* Write disable */
#define QSPI_FLASH_CMD_RDSR1 0x05      /* Read status register */
#define QSPI_FLASH_CMD_WREN 0x06       /* Write enable */
#define QSPI_FLASH_CMD_RDSR2 0x07      /* Read status register */
#define QSPI_FLASH_CMD_FAST_READ 0x0B  /* Fast read data bytes */
#define QSPI_FLASH_CMD_4FAST_READ 0x0C /* Fast read data bytes */
#define QSPI_FLASH_CMD_4PP 0x12        /* Page program */
#define QSPI_FLASH_CMD_4READ 0x13      /* Normal read data bytes */
#define QSPI_FLASH_CMD_P4E 0x20        /* Erase 4kb sector */
#define QSPI_FLASH_CMD_4P4E 0x21       /* Erase 4kb sector */
#define QSPI_FLASH_CMD_QPP 0x32        /* Quad Page program */
#define QSPI_FLASH_CMD_4QPP 0x34       /* Quad Page program */
#define QSPI_FLASH_CMD_RDCR 0x35       /* Read config register */
#define QSPI_FLASH_CMD_BE 0x60         /* Bulk erase */
#define QSPI_FLASH_CMD_RDAR 0x65       /* Read Any Register  */
#define QSPI_FLASH_CMD_QOR 0x6B        /* Quad read data bytes */
#define QSPI_FLASH_CMD_4QOR 0x6C       /* Quad read data bytes */
#define QSPI_FLASH_CMD_WRAR 0x71       /* Write Any Register  */
#define QSPI_FLASH_CMD_RDID 0x9F       /* Read JEDEC ID */
#define QSPI_FLASH_CMD_4BAM 0xB7       /* Enter 4 Bytes Mode */
#define QSPI_FLASH_CMD_4BE 0xC7        /* Bulk erase */
#define QSPI_FLASH_CMD_SE 0xD8         /* Sector erase */
#define QSPI_FLASH_CMD_4SE 0xDC        /* Sector erase */
#define QSPI_FLASH_CMD_4BEX 0xE9       /* Exit 4 Bytes Mode */
#define QSPI_FLASH_CMD_QIOR 0xEB       /* Quad read data bytes */
#define QSPI_FLASH_CMD_4QIOR 0xEC      /* Quad read data bytes */
#define QSPI_FLASH_CMD_SFDP 0x5A       /* Read JEDEC Serial Manu ID */

#define QSPI_BUSY_TIMEOUT_US    100000

typedef struct
{
    u32 instanceId;  /* Id of device */
    intptr baseAddr; /* Base address of qspi */
    intptr memStart; /* Start address of qspi memory */
    u32 transMode;   /* Transfer mode */
    u32 capacity;    /* Flash capacity */
    u32 addrMode;    /* Addr mode: 3 byte/4 byte */
    u32 clkDiv;      /* Clock div */
    u32 devNum;      /* Qspi device number */
    u32 channel;     /* Cs number */
    u32 bitWidth;    /* Transfer unit width */
} QSpiConfig;

typedef struct
{
    QSpiConfig config;
    u32 isReady;         /**< Device is initialized and ready */
    u32 flashSize;       /* size of QSPI flash */   
} QSpiCtrl;

const QSpiConfig *NorFlashLookupConfig(u32 instanceId);
u32 NorFlashInit(QSpiCtrl *pCtrl, const QSpiConfig *pConfig);
u32 FSpiSetOptions(QSpiCtrl *pCtrl, QSpiOptions options, u32 value);
u32 NorFlashReadReg(QSpiCtrl *pCtrl, u32 opCode, u8 *pBuf, size_t len);
u32 NorFlashWriteReg(QSpiCtrl *pCtrl, u32 opCode, const u8 *pBuf, size_t len);
u32 NorFlashRead(QSpiCtrl *pCtrl, u32 opCode, u32 inChipAddr, u8 *pBuf, size_t len);
u32 NorFlashWrite(QSpiCtrl *pCtrl, u32 opCode, u32 inChipAddr, const u8 *pBuf, size_t len);
u32 NorFlashErase(QSpiCtrl *pCtrl, u32 opCode, u32 offset);

#ifdef __cplusplus
}
#endif

#endif
